home *** CD-ROM | disk | FTP | other *** search
/ PD Collection CD 1 / PD Collection CD 1.iso / textual / tex / files / !tex / TeXsource / commontex / c / mlisthlist < prev    next >
Encoding:
Text File  |  1988-04-08  |  20.0 KB  |  1,018 lines

  1. /*
  2.  *    Copyright 1986, 1987 Pat Joseph Monardo. All rights reserved.
  3.  *    Copying of this file is granted according to the provisions 
  4.  *    specified in the file COPYING which must accompany this file.
  5.  */
  6.  
  7.  
  8. /*
  9.  *        mlist-hlist.c
  10.  */
  11.  
  12. #include "tex.h"
  13. #include "heap.h"
  14. #include "arith.h"
  15. #include "scan.h"
  16. #include "eq.h"
  17. #include "box.h"
  18. #include "math.h"
  19. #include "pack.h"
  20. #include "tfm.h"
  21. #include "print.h"
  22. #include "error.h"
  23. #include "str.h"
  24. #include "mlisthlist.h"
  25.  
  26. qword    cur_c;
  27. fnt        cur_f;
  28. fourq    cur_i;
  29. scal    cur_mu;
  30. int        cur_size;
  31. int        cur_style;
  32. ptr        cur_mlist;
  33. bool    mlist_penalties;
  34.  
  35. ptr
  36. clean_box (p, s)
  37.     ptr        p;
  38.     int        s;
  39. {
  40.     ptr        q;
  41.     ptr        r;
  42.     ptr        x;
  43.     int        save_style;
  44.  
  45.     switch (math_type(p))
  46.     {
  47.     case MATH_CHAR:
  48.         cur_mlist = new_noad();
  49.         mem[nucleus(cur_mlist)] = mem[p];
  50.         break;
  51.  
  52.     case SUB_BOX:
  53.         q = info(p);
  54.         goto found; 
  55.         break;    
  56.     
  57.     case SUB_MLIST:
  58.         cur_mlist = info(p);
  59.         break;
  60.     
  61.     default:
  62.         q = new_null_box();
  63.         goto found;
  64.         break;
  65.     }
  66.     save_style = cur_style;
  67.     cur_style = s;
  68.     mlist_penalties = FALSE;
  69.     mlist_to_hlist();
  70.     q = link(temp_head);
  71.     cur_style = save_style;
  72.     change_size_and_mu();
  73.  
  74. found:
  75.     if (is_char_node(q) || q == NULL)
  76.         x = hpack(q, NATURAL);    
  77.     else if (link(q) == NULL &&
  78.             type(q) <= VLIST_NODE &&
  79.             shift_amount(q) == 0)
  80.             x = q;
  81.     else x = hpack(q, NATURAL);
  82.     q = list_ptr(x);
  83.     if (is_char_node(q)) {
  84.         r = link(q);
  85.         if (r != NULL &&
  86.             link(r) == NULL &&    
  87.             !is_char_node(r) &&
  88.             type(r) == KERN_NODE) {
  89.             free_node(r, SMALL_NODE_SIZE);
  90.             link(q) = NULL;
  91.         }
  92.     }
  93.     return x;
  94. }
  95.  
  96. fetch (a)
  97.     ptr        a;
  98. {
  99.     cur_c = character(a);
  100.     cur_f = fam_fnt(fam(a) + cur_size);
  101.     if (cur_f == NULL_FONT) {
  102.         print_err("");
  103.         print_size(cur_size);
  104.         print_char(' ');
  105.         print_int(fam(a));
  106.         print(" is undefined (character ");
  107.         print_ASCII(qo(cur_c));
  108.         print_char(')');
  109.         help_undefd_mathchar();
  110.         error();
  111.         cur_i = null_character;
  112.         math_type(a) = EMPTY;
  113.     } else {
  114.         if (qo(cur_c) >= font_bc[cur_f] &&
  115.             qo(cur_c) <= font_ec[cur_f])
  116.             cur_i = char_info(cur_f, cur_c);
  117.         else cur_i = null_character;
  118.         if (!char_exists(cur_i)) {
  119.             char_warning(cur_f, qo(cur_c));
  120.             math_type(a) = EMPTY;
  121.         }
  122.     }
  123. }
  124.  
  125. char    math_spacing[] = 
  126.         "0234000122*4000133**3**344*0400400*000000234000111*1111112341011";
  127.  
  128. #define    choose_mlist(L) \
  129.     {p = L(q); L(q) = NULL;}
  130.  
  131. mlist_to_hlist ()
  132. {
  133.     ptr        p;
  134.     ptr        q;
  135.     ptr        r;
  136.     int        s;
  137.     int        t;
  138.     ptr        x;
  139.     ptr        y;
  140.     ptr        z;
  141.     val        pen;
  142.     scal    delta;
  143.     scal    max_d;
  144.     scal    max_h;
  145.     ptr        mlist;
  146.     int        style;
  147.     int        r_type;
  148.     bool    penalties;
  149.     int        save_style;
  150.  
  151.     mlist = cur_mlist;
  152.     penalties = mlist_penalties;
  153.     style = cur_style;
  154.     q = mlist;
  155.     r = NULL;
  156.     r_type = OP_NOAD;
  157.     max_h = 0;
  158.     max_d = 0;
  159.     change_size_and_mu();
  160.  
  161.     while (q != NULL)
  162.     {
  163. reswitch:
  164.         delta = 0;
  165.         switch (type(q))
  166.         {
  167.         case BIN_NOAD:    
  168.             switch (r_type)
  169.             {
  170.             case BIN_NOAD:
  171.             case OP_NOAD:
  172.             case REL_NOAD:
  173.             case OPEN_NOAD:
  174.             case PUNCT_NOAD:
  175.             case LEFT_NOAD:
  176.                 type(q) = ORD_NOAD;
  177.                 goto reswitch;
  178.                 break;
  179.  
  180.             default:
  181.                 break;
  182.             }
  183.             break;
  184.  
  185.         case REL_NOAD:
  186.         case CLOSE_NOAD:
  187.         case PUNCT_NOAD:
  188.         case RIGHT_NOAD:
  189.             if (r_type == BIN_NOAD)
  190.                 type(r) = ORD_NOAD;
  191.             if (type(q) == RIGHT_NOAD)
  192.                 goto done_with_noad;
  193.             break;
  194.  
  195.         case LEFT_NOAD:
  196.             goto done_with_noad;
  197.             break;
  198.  
  199.         case FRACTION_NOAD:
  200.             make_fraction(q);
  201.             goto check_dimensions;
  202.             break;
  203.         
  204.         case OP_NOAD:
  205.             delta = make_op(q);
  206.             if (subtype(q) == LIMITS)
  207.                 goto check_dimensions;
  208.             break;
  209.  
  210.         case ORD_NOAD:
  211.             make_ord(q);
  212.             break;
  213.  
  214.         case OPEN_NOAD:
  215.         case INNER_NOAD:
  216.             break;
  217.         
  218.         case RADICAL_NOAD:
  219.             make_radical(q);
  220.             break;
  221.         
  222.         case OVER_NOAD:
  223.             make_over(q);
  224.             break;
  225.  
  226.         case UNDER_NOAD:
  227.             make_under(q);
  228.             break;
  229.     
  230.         case ACCENT_NOAD:
  231.             make_math_accent(q);
  232.             break;
  233.         
  234.         case VCENTER_NOAD:
  235.             make_vcenter(q);
  236.             break;
  237.         
  238.         case STYLE_NODE:
  239.             cur_style = subtype(q);
  240.             change_size_and_mu();
  241.             goto done_with_node;
  242.             break;
  243.         
  244.         case CHOICE_NODE:
  245.             switch (cur_style / 2)
  246.             {
  247.             case 0:
  248.                 choose_mlist(display_mlist);
  249.                 break;
  250.  
  251.             case 1:
  252.                 choose_mlist(text_mlist);
  253.                 break;
  254.  
  255.             case 2:
  256.                 choose_mlist(script_mlist);
  257.                 break;
  258.  
  259.             case 3:
  260.                 choose_mlist(script_script_mlist);
  261.                 break;
  262.             }
  263.             flush_node_list(display_mlist(q));
  264.             flush_node_list(text_mlist(q));
  265.             flush_node_list(script_mlist(q));
  266.             flush_node_list(script_script_mlist(q));
  267.             type(q) = STYLE_NODE;
  268.             subtype(q) = cur_style;
  269.             width(q) = 0;
  270.             depth(q) = 0;
  271.             if (p != NULL) {
  272.                 z = link(q);
  273.                 link(q) = p;
  274.                 while (link(p) != NULL)
  275.                     p = link(p);
  276.                 link(p) = z;
  277.             }
  278.             goto done_with_node;
  279.             break;
  280.  
  281.         case INS_NODE:
  282.         case MARK_NODE:
  283.         case ADJUST_NODE:
  284.         case WHATSIT_NODE:
  285.         case PENALTY_NODE:
  286.         case DISC_NODE:
  287.             goto done_with_node;
  288.             break;
  289.         
  290.         case RULE_NODE:
  291.             if (height(q) > max_h)
  292.                 max_h = height(q);
  293.             if (depth(q) > max_d)
  294.                 max_d = depth(q);
  295.             goto done_with_node;
  296.             break;
  297.  
  298.         case GLUE_NODE:
  299.             if (subtype(q) == MU_GLUE) {
  300.                 x = glue_ptr(q);
  301.                 y = math_glue(x, cur_mu);
  302.                 delete_glue_ref(x);
  303.                 glue_ptr(q) = y;
  304.                 subtype(q) = NORMAL;
  305.             } else if (cur_size != TEXT_SIZE &&
  306.                 subtype(q) == COND_MATH_GLUE) {
  307.                 p = link(q);
  308.                 if (p != NULL &&
  309.                     (type(p) == GLUE_NODE ||
  310.                     type(p) == KERN_NODE)) {
  311.                     link(q) = link(p);
  312.                     link(p) = NULL;
  313.                     flush_node_list(p);
  314.                 }
  315.             }
  316.             goto done_with_node;
  317.             break;
  318.         
  319.         case KERN_NODE:
  320.             math_kern(q, cur_mu);
  321.             goto done_with_node;
  322.             break;
  323.         
  324.         default:
  325.             confusion("mlist1");
  326.         }
  327.  
  328.         switch (math_type(nucleus(q)))
  329.         {
  330.         case MATH_CHAR:
  331.         case MATH_TEXT_CHAR:
  332.             fetch(nucleus(q));
  333.             if (char_exists(cur_i)) {
  334.                 delta = char_italic(cur_f, cur_i);
  335.                 p = new_character(cur_f, qo(cur_c));
  336.                 if (math_type(nucleus(q)) == MATH_TEXT_CHAR &&
  337.                     space(cur_f) != 0)
  338.                     delta = 0;
  339.                 if (math_type(subscr(q)) == EMPTY && delta != 0) {
  340.                     link(p) = new_kern(delta);
  341.                     delta = 0;
  342.                 }
  343.             } else
  344.                 p = NULL;
  345.             break;
  346.         
  347.         case EMPTY:
  348.             p = NULL;
  349.             break;
  350.  
  351.         case SUB_BOX:
  352.             p = info(nucleus(q));
  353.             break;
  354.  
  355.         case SUB_MLIST:
  356.             cur_mlist = info(nucleus(q));
  357.             save_style = cur_style;
  358.             mlist_penalties = FALSE;
  359.             mlist_to_hlist();
  360.             cur_style = save_style;
  361.             change_size_and_mu();
  362.             p = hpack(link(temp_head), NATURAL); 
  363.             break;
  364.  
  365.         default:
  366.             confusion("mlist2");
  367.         }
  368.         new_hlist(q) = p;
  369.         if (math_type(subscr(q)) == EMPTY && 
  370.             math_type(supscr(q)) == EMPTY)
  371.             goto check_dimensions;
  372.         make_scripts(q, delta);
  373.         
  374. check_dimensions:
  375.         z = hpack((ptr)new_hlist(q), NATURAL);
  376.         if (height(z) > max_h)
  377.             max_h = height(z);
  378.         if (depth(z) > max_d)
  379.             max_d = depth(z);
  380.         free_node(z, BOX_NODE_SIZE);
  381.  
  382. done_with_noad:
  383.         r = q;
  384.         r_type = type(r);
  385.  
  386. done_with_node:
  387.         q = link(q);
  388.     } 
  389.  
  390.     if (r_type == BIN_NOAD)
  391.         type(r) = ORD_NOAD;
  392.     p = temp_head;
  393.     link(p) = NULL;
  394.     q = mlist;
  395.     r_type = 0;
  396.     cur_style = style;
  397.     change_size_and_mu();
  398.  
  399.     while (q != NULL) {
  400.         t = ORD_NOAD;
  401.         s = NOAD_SIZE;
  402.         pen = INF_PENALTY;
  403.         switch (type(q))
  404.         {
  405.         case OP_NOAD:
  406.         case OPEN_NOAD:
  407.         case CLOSE_NOAD:
  408.         case PUNCT_NOAD:
  409.         case INNER_NOAD:
  410.             t = type(q);
  411.             break;
  412.         
  413.         case BIN_NOAD:
  414.             t = BIN_NOAD;
  415.             pen = bin_op_penalty;
  416.             break;
  417.         
  418.         case REL_NOAD:
  419.             t = REL_NOAD;
  420.             pen = rel_penalty;
  421.             break; 
  422.         
  423.         case ORD_NOAD:
  424.         case VCENTER_NOAD:
  425.         case OVER_NOAD:
  426.         case UNDER_NOAD:
  427.             break;
  428.  
  429.         case RADICAL_NOAD:
  430.             s = RADICAL_NOAD_SIZE;
  431.             break;
  432.  
  433.         case ACCENT_NOAD:
  434.             s = ACCENT_NOAD_SIZE;
  435.             break;
  436.  
  437.         case FRACTION_NOAD:
  438.             t = INNER_NOAD;
  439.             s = FRACTION_NOAD_SIZE;
  440.             break;
  441.  
  442.         case LEFT_NOAD:
  443.         case RIGHT_NOAD:
  444.             t = make_left_right(q, style, max_d, max_h);
  445.             break;
  446.         
  447.         case STYLE_NODE:
  448.             cur_style = subtype(q);
  449.             s = STYLE_NODE_SIZE;
  450.             change_size_and_mu();
  451.             goto delete_q;
  452.             break;
  453.  
  454.         case WHATSIT_NODE:
  455.         case PENALTY_NODE:
  456.         case RULE_NODE:
  457.         case DISC_NODE:
  458.         case ADJUST_NODE:
  459.         case INS_NODE:
  460.         case MARK_NODE:
  461.         case GLUE_NODE:
  462.         case KERN_NODE:
  463.             link(p) = q;
  464.             p = q;
  465.             q = link(q);
  466.             link(p) = NULL;
  467.             continue;
  468.         
  469.         default:
  470.             confusion("mlist3");
  471.         }
  472.  
  473.         if (r_type > 0) {
  474.             switch (math_spacing[r_type * 8 + t + magic_offset]) 
  475.             {
  476.             case '0':
  477.                 x = 0;
  478.                 break;
  479.  
  480.             case '1':
  481.                 if (cur_style < SCRIPT_STYLE)
  482.                     x = THIN_MU_SKIP_CODE;
  483.                 else x = 0;
  484.                 break;
  485.  
  486.             case '2':
  487.                 x = THIN_MU_SKIP_CODE;
  488.                 break;
  489.  
  490.             case '3':
  491.                 if (cur_style < SCRIPT_STYLE)
  492.                     x = MED_MU_SKIP_CODE;
  493.                 else x = 0;
  494.                 break;
  495.  
  496.             case '4':
  497.                 if (cur_style < SCRIPT_STYLE)
  498.                     x = THICK_MU_SKIP_CODE;
  499.                 else x = 0;
  500.                 break;
  501.  
  502.             default:
  503.                 confusion("mlist4");
  504.                 break;
  505.             }
  506.             if (x != 0) {
  507.                 y = math_glue(glue_par(x), cur_mu);
  508.                 z = new_glue(y);
  509.                 glue_ref_count(y) = NULL;
  510.                 link(p) = z;
  511.                 p = z;
  512.                 subtype(z) = x + 1;
  513.             }
  514.         }
  515.         if (new_hlist(q) != NULL) {
  516.             link(p) = new_hlist(q);
  517.             do p = link(p);
  518.             while (link(p) != NULL);
  519.         }
  520.         if (penalties && link(q) != NULL && pen < INF_PENALTY) {
  521.             r_type = type(link(q));
  522.             if (r_type != PENALTY_NODE && r_type != REL_NOAD) {
  523.                 z = new_penalty(pen);
  524.                 link(p) = z;
  525.                 p = z;
  526.             }
  527.         }
  528.         r_type = t;
  529.  
  530. delete_q:
  531.         r = q;
  532.         q = link(q);
  533.         free_node(r, s);
  534.     }
  535. }
  536.  
  537. make_over (q)
  538.     ptr    q;
  539. {
  540.     info(nucleus(q)) =
  541.         overbar(clean_box(nucleus(q), cramped_style(cur_style)),
  542.                 3 * default_rule_thickness, default_rule_thickness);
  543.     math_type(nucleus(q)) = SUB_BOX;
  544. }
  545.  
  546. make_under (q)
  547.     ptr     q;
  548. {
  549.     ptr        p;
  550.     ptr        x;
  551.     ptr        y;
  552.     scal    delta;
  553.  
  554.     x = clean_box(nucleus(q), cur_style);
  555.     p = new_kern(3 * default_rule_thickness);
  556.     link(x) = p;
  557.     link(p) = fraction_rule(default_rule_thickness);
  558.     y = vpack(x, NATURAL);
  559.     delta = height(y) + depth(y) + default_rule_thickness;
  560.     height(y) = height(x);
  561.     depth(y) = delta - height(y);
  562.     info(nucleus(q)) = y;
  563.     math_type(nucleus(q)) = SUB_BOX;
  564. }
  565.  
  566. make_vcenter (q)
  567.     ptr        q;
  568. {
  569.     ptr        v;
  570.     scal    delta;
  571.  
  572.     v = info(nucleus(q));
  573.     if (type(v) != VLIST_NODE)
  574.         confusion("vcenter");
  575.     delta = height(v) + depth(v);
  576.     height(v) = axis_height(cur_size) + half(delta);
  577.     depth(v) = delta - height(v);
  578. }
  579.  
  580. make_radical (q)
  581.     ptr        q;
  582. {
  583.     ptr        x;
  584.     ptr        y;
  585.     scal    clr;
  586.     scal    delta;
  587.  
  588.     x = clean_box(nucleus(q), cramped_style(cur_style));
  589.     if (cur_style < TEXT_STYLE)
  590.         clr = default_rule_thickness + (abs(math_x_height(cur_size)) / 4);
  591.     else {
  592.         clr = default_rule_thickness;
  593.         clr += (abs(clr) / 4);
  594.     }
  595.     y = var_delimiter(left_delimiter(q), cur_size,
  596.                         height(x) + depth(x) + clr + default_rule_thickness);
  597.     delta = depth(y) - (height(x) + depth(x) + clr);
  598.     if (delta > 0) clr += half(delta);
  599.     shift_amount(y) = -(height(x) + clr);
  600.     link(y)  = overbar(x, clr, height(y));
  601.     info(nucleus(q)) = hpack(y, NATURAL);
  602.     math_type(nucleus(q)) = SUB_BOX;
  603. }
  604.  
  605. make_math_accent (q)
  606.     ptr        q;
  607. {
  608.     int        a;
  609.     qword    c;
  610.     fnt        f;
  611.     scal    h;
  612.     fourq    i;
  613.     ptr        p;
  614.     scal    s;
  615.     scal    w;
  616.     ptr        x;
  617.     ptr        y;
  618.     scal    delta;
  619.  
  620.     fetch(accent_chr(q)); 
  621.     if (char_exists(cur_i)) {
  622.         i = cur_i;
  623.         c = cur_c;
  624.         f = cur_f;
  625.         s = 0;
  626.         if (math_type(nucleus(q)) == MATH_CHAR) {
  627.             fetch(nucleus(q));
  628.             if (char_tag(cur_i) == LIG_TAG) {
  629.                 a = lig_kern_start(cur_f, cur_i);
  630.                 do    {
  631.                     cur_i = font_info[a].qqqq;
  632.                     if (qo(next_char(cur_i)) == skew_char[cur_f]) {
  633.                         if (op_bit(cur_i) >= KERN_FLAG)
  634.                             s = char_kern(cur_f, cur_i);
  635.                         break;
  636.                     }
  637.                     incr(a);
  638.                 } while (stop_bit(cur_i) < STOP_FLAG);
  639.             }
  640.         }
  641.         x = clean_box(nucleus(q), cramped_style(cur_style));
  642.         w = width(x);
  643.         h = height(x);
  644.         loop {
  645.             if (char_tag(i) != LIST_TAG)
  646.                 break;
  647.             y = rem_byte(i);
  648.             i = char_info(f, y);
  649.             if (char_width(f, i) > w)
  650.                 break;
  651.             c = y;
  652.         }
  653.         delta = (h < x_height(f) ? h : x_height(f));
  654.         if ((math_type(supscr(q)) != EMPTY ||
  655.             math_type(subscr(q)) != EMPTY) &&
  656.             math_type(nucleus(q)) == MATH_CHAR) {
  657.                 flush_node_list(x);
  658.                 x = new_noad(); 
  659.                 mem[nucleus(x)] = mem[nucleus(q)];
  660.                 mem[supscr(x)] = mem[supscr(q)];
  661.                 mem[subscr(x)] = mem[subscr(q)];
  662.                 mem[supscr(q)].hh = empty_field;
  663.                 mem[subscr(q)].hh = empty_field;
  664.                 math_type(nucleus(q)) = SUB_MLIST;
  665.                 info(nucleus(q)) = x;
  666.                 x = clean_box(nucleus(q), cur_style);
  667.                 delta = delta + height(x) - h;
  668.                 h = height(x);
  669.         }
  670.         y = char_box(f, c);
  671.         shift_amount(y) = s + half(w - width(y));
  672.         width(y) = 0;
  673.         p = new_kern(-delta);
  674.         link(p) = x;
  675.         link(y) = p;
  676.         y = vpack(y, NATURAL);
  677.         width(y) = width(x);
  678.         if (height(y) < h) {
  679.             p = new_kern(h - height(y));
  680.             link(p) = list_ptr(y);
  681.             list_ptr(y) = p;
  682.             height(y) = h;
  683.         }
  684.         info(nucleus(q)) = y;
  685.         math_type(nucleus(q)) = SUB_BOX;
  686.     }
  687. }
  688.  
  689. make_fraction (q)
  690.     ptr        q;
  691. {
  692.     ptr        p;
  693.     ptr        v;
  694.     ptr        x;
  695.     ptr        y;
  696.     ptr        z;
  697.     scal    clr;
  698.     scal    delta;
  699.     scal    delta1;
  700.     scal    delta2;
  701.     scal    shift_up;
  702.     scal    shift_down;
  703.  
  704.     if (thickness(q) == DEFAULT_CODE)
  705.         thickness(q) = default_rule_thickness;
  706.     x = clean_box(numerator(q), num_style(cur_style));
  707.     z = clean_box(denominator(q), denom_style(cur_style));
  708.     if (width(x) < width(z))
  709.         x = rebox(x, width(z));
  710.     else z = rebox(z, width(x));
  711.     if (cur_style < TEXT_STYLE) {
  712.         shift_up = num1(cur_size);
  713.         shift_down = denom1(cur_size);
  714.     } else {
  715.         shift_down = denom2(cur_size);
  716.         if (thickness(q) != 0)
  717.             shift_up = num2(cur_size);
  718.         else shift_up = num3(cur_size);
  719.     }
  720.     if (thickness(q) == 0) {
  721.         if (cur_style < TEXT_STYLE)
  722.             clr = 7 * default_rule_thickness;
  723.         else clr = 3 * default_rule_thickness;
  724.         delta = half(clr - ((shift_up - depth(x)) - (height(z) - shift_down)));
  725.         if (delta > 0) {
  726.             shift_up += delta;
  727.             shift_down += delta;
  728.         }
  729.     } else {
  730.         if (cur_style < TEXT_STYLE)
  731.             clr = 3 * thickness(q);
  732.         else clr = thickness(q);
  733.         delta = half(thickness(q));
  734.         delta1 = clr -
  735.             ((shift_up - depth(x)) - (axis_height(cur_size) + delta));
  736.         delta2 = clr - 
  737.             ((axis_height(cur_size) - delta) - (height(z) - shift_down));
  738.         if (delta1 > 0) shift_up += delta1;
  739.         if (delta2 > 0) shift_down += delta2;
  740.     }
  741.     v = new_null_box();
  742.     type(v) = VLIST_NODE;
  743.     height(v) = shift_up + height(x);
  744.     depth(v) = depth(z) + shift_down;
  745.     width(v) = width(x);
  746.     if (thickness(q) == 0) {
  747.         p = new_kern((shift_up - depth(x)) - (height(z) - shift_down));
  748.         link(p) = z;
  749.     } else {
  750.         y = fraction_rule(thickness(q));
  751.         p = new_kern((axis_height(cur_size)-delta) - (height(z)-shift_down));
  752.         link(y) = p;
  753.         link(p) = z;
  754.         p = new_kern((shift_up - depth(x)) - (axis_height(cur_size) + delta));
  755.         link(p)  = y;
  756.     }
  757.     link(x) = p;
  758.     list_ptr(v) = x;
  759.     if (cur_style < TEXT_STYLE)
  760.         delta = delim1(cur_size);
  761.     else delta = delim2(cur_size);
  762.     x = var_delimiter(left_delimiter(q), cur_size, delta);
  763.     link(x) = v;
  764.     z = var_delimiter(right_delimiter(q), cur_size, delta);
  765.     link(v) = z;
  766.     new_hlist(q) = hpack(x, NATURAL);
  767. }
  768.  
  769. scal
  770. make_op (q)
  771.     ptr        q;
  772. {
  773.     ptr        p;
  774.     ptr        v;
  775.     ptr        x;
  776.     ptr        y;
  777.     ptr        z;
  778.     scal    delta;
  779.     scal    shift_up;
  780.     scal    shift_down;
  781.  
  782.     if (subtype(q) == NORMAL && cur_style < TEXT_STYLE)
  783.         subtype(q) = LIMITS;
  784.     if (math_type(nucleus(q)) == MATH_CHAR) {
  785.         fetch(nucleus(q));
  786.         if (cur_style < TEXT_STYLE && char_tag(cur_i) == LIST_TAG) {
  787.             cur_c = rem_byte(cur_i);
  788.             character(nucleus(q)) = cur_c;
  789.             cur_i = char_info(cur_f, cur_c);
  790.         }
  791.         delta = char_italic(cur_f, cur_i);
  792.         x = clean_box(nucleus(q), cur_style);
  793.         if (math_type(subscr(q)) != EMPTY && subtype(q) != LIMITS)
  794.             width(x) -= delta;
  795.         shift_amount(x) = half(height(x) - depth(x)) - axis_height(cur_size);
  796.         math_type(nucleus(q)) = SUB_BOX;
  797.         info(nucleus(q)) = x;
  798.     } else delta = 0;
  799.     if (subtype(q) == LIMITS) {
  800.         x = clean_box(supscr(q), sup_style(cur_style));
  801.         y = clean_box(nucleus(q), cur_style);
  802.         z = clean_box(subscr(q), sub_style(cur_style));
  803.         v = new_null_box();
  804.         type(v) = VLIST_NODE;
  805.         width(v) = width(y);
  806.         if (width(x) > width(v))
  807.             width(v) = width(x);
  808.         if (width(z) > width(v))
  809.             width(v) = width(z);
  810.         x = rebox(x, width(v));
  811.         y = rebox(y, width(v));
  812.         z = rebox(z, width(v));
  813.         shift_amount(x) = half(delta);
  814.         shift_amount(z) = -shift_amount(x);
  815.         height(v) = height(y);
  816.         depth(v) = depth(y);
  817.         if (math_type(supscr(q)) == EMPTY) {
  818.             free_node(x, BOX_NODE_SIZE);
  819.             list_ptr(v) = y;
  820.         } else {
  821.             shift_up = big_op_spacing3 - depth(x);
  822.             if (shift_up < big_op_spacing1)
  823.                 shift_up = big_op_spacing1;
  824.             p = new_kern(shift_up);
  825.             link(p) = y;
  826.             link(x) = p;
  827.             p = new_kern(big_op_spacing5);
  828.             link(p) = x;
  829.             list_ptr(v) = p;
  830.             height(v) += big_op_spacing5 + height(x) + depth(x) + shift_up;
  831.         }
  832.         if (math_type(subscr(q)) == EMPTY)
  833.             free_node(z, BOX_NODE_SIZE);
  834.         else {
  835.             shift_down = big_op_spacing4 - height(z);
  836.             if (shift_down < big_op_spacing2)
  837.                 shift_down = big_op_spacing2;
  838.             p = new_kern(shift_down);
  839.             link(y) = p;
  840.             link(p) = z;
  841.             p = new_kern(big_op_spacing5);
  842.             link(z) = p;
  843.             depth(v) += big_op_spacing5 + height(z) + depth(z) + shift_down;
  844.         }
  845.         new_hlist(q) = v;
  846.     }
  847.     return delta;
  848. }
  849.  
  850. make_ord (q)
  851.     ptr        q;
  852. {
  853.     int        a;
  854.     ptr        p;
  855.  
  856. restart:
  857.     if (math_type(subscr(q)) == EMPTY &&
  858.         math_type(supscr(q)) == EMPTY &&
  859.         math_type(nucleus(q)) == MATH_CHAR) {
  860.         p = link(q);
  861.         if (p != NULL &&
  862.             type(p) >= ORD_NOAD &&
  863.             type(p) <= PUNCT_NOAD &&
  864.             math_type(nucleus(p)) == MATH_CHAR &&
  865.             fam(nucleus(p)) == fam(nucleus(q))) {
  866.             math_type(nucleus(q)) = MATH_TEXT_CHAR;
  867.             fetch(nucleus(q));
  868.             if (char_tag(cur_i) == LIG_TAG) {
  869.                 a = lig_kern_start(cur_f, cur_i);
  870.                 cur_c = character(nucleus(p));
  871.                 do    {
  872.                     cur_i = font_info[a].qqqq;
  873.                     if (next_char(cur_i) == cur_c) {
  874.                         if (op_bit(cur_i) >= KERN_FLAG) {
  875.                             p = new_kern(char_kern(cur_f, cur_i));
  876.                             link(p) = link(q);
  877.                             link(q) = p;
  878.                             return;
  879.                         } else {
  880.                             link(q) = link(p);
  881.                             math_type(nucleus(q)) = MATH_CHAR;
  882.                             character(nucleus(q)) = rem_byte(cur_i);
  883.                             mem[subscr(q)] = mem[subscr(p)];
  884.                             mem[supscr(q)] = mem[supscr(p)];
  885.                             free_node(p, NOAD_SIZE);
  886.                             goto restart;
  887.                         }
  888.                     }
  889.                     incr(a);
  890.                 } while (stop_bit(cur_i) < STOP_FLAG);
  891.             }
  892.         }
  893.     }
  894. }
  895.  
  896. make_scripts (q, delta)
  897.     ptr        q;
  898.     scal    delta;
  899. {
  900.     ptr        p;
  901.     int        t;
  902.     ptr        x;
  903.     ptr        y;
  904.     ptr        z;
  905.     scal    clr;
  906.     scal    shift_up;
  907.     scal    shift_down;
  908.  
  909.     p = new_hlist(q);
  910.     if (is_char_node(p)) {
  911.         shift_up = 0;
  912.         shift_down = 0;
  913.     } else {
  914.         z = hpack(p, NATURAL);
  915.         if (cur_style < SCRIPT_STYLE)    
  916.             t = SCRIPT_SIZE;
  917.         else t = SCRIPT_SCRIPT_SIZE;
  918.         shift_up = height(z) - sup_drop(t);
  919.         shift_down = depth(z) + sub_drop(t);
  920.         free_node(z, BOX_NODE_SIZE);
  921.     }
  922.     if (math_type(supscr(q)) == EMPTY) {
  923.         x = clean_box(subscr(q), sub_style(cur_style));
  924.         width(x) += script_space;
  925.         if (shift_down < sub1(cur_size))
  926.             shift_down = sub1(cur_size);
  927.         clr = height(x) - (abs(math_x_height(cur_size) * 4) / 5);
  928.         if (shift_down < clr)
  929.             shift_down = clr;
  930.         shift_amount(x) = shift_down;
  931.     } else {
  932.         x = clean_box(supscr(q), sup_style(cur_style));
  933.         width(x) += script_space;
  934.         if (odd(cur_style))
  935.             clr = sup3(cur_size);
  936.         else if (cur_style < TEXT_STYLE)
  937.             clr = sup1(cur_size);
  938.         else clr = sup2(cur_size);
  939.         if (shift_up < clr)
  940.             shift_up = clr;
  941.         clr = depth(x) + (abs(math_x_height(cur_size)) / 4);
  942.         if (shift_up < clr)
  943.             shift_up = clr;
  944.         if (math_type(subscr(q)) == EMPTY) 
  945.             shift_amount(x) = -shift_up;
  946.         else {
  947.             y = clean_box(subscr(q), sub_style(cur_style));
  948.             width(y) += script_space;
  949.             if (shift_down < sub2(cur_size))
  950.                 shift_down = sub2(cur_size);
  951.             clr = 4 * default_rule_thickness -
  952.                         ((shift_up - depth(x)) - (height(y) - shift_down));
  953.             if (clr > 0) {
  954.                 shift_down += clr;
  955.                 clr = (abs(math_x_height(cur_size) * 4) / 5) -
  956.                         (shift_up - depth(x));
  957.                 if (clr > 0) {
  958.                     shift_up += clr;
  959.                     shift_down -= clr;
  960.                 }
  961.             }
  962.             shift_amount(x) = delta;
  963.             p = new_kern((shift_up - depth(x)) - (height(y) - shift_down));
  964.             link(x) = p;
  965.             link(p) = y;
  966.             x = vpack(x, NATURAL);
  967.             shift_amount(x) = shift_down;
  968.         }
  969.     }
  970.     if (new_hlist(q) == NULL)
  971.         new_hlist(q) = x;
  972.     else {
  973.         p = new_hlist(q);
  974.         while (link(p) != NULL)
  975.             p = link(p);
  976.         link(p) = x;
  977.     }
  978. }
  979.  
  980. make_left_right (q, style, max_d, max_h)
  981.     ptr        q;
  982.     int        style;
  983.     scal    max_d;
  984.     scal    max_h;
  985. {
  986.     scal    delta;
  987.     scal    delta1;
  988.     scal    delta2;
  989.  
  990.     if (style  < SCRIPT_STYLE)
  991.         cur_size = TEXT_SIZE;
  992.     else cur_size = 16 * ((style - TEXT_STYLE) / 2);
  993.     delta2 = max_d + axis_height(cur_size);
  994.     delta1 = max_h + max_d - delta2;
  995.     if (delta2 > delta1)
  996.         delta1 = delta2;
  997.     delta = (delta1 / 500) * delimiter_factor;
  998.     delta2 = delta1 + delta1 - delimiter_shortfall;
  999.     if (delta < delta2)
  1000.         delta = delta2;
  1001.     new_hlist(q) = var_delimiter(delimiter(q), cur_size, delta);
  1002.     return (type(q) - (LEFT_NOAD - OPEN_NOAD));
  1003. }
  1004.  
  1005. int        magic_offset = - 9 * ORD_NOAD;
  1006.  
  1007. /*
  1008.  *    Help text
  1009.  */
  1010.  
  1011. help_undefd_mathchar ()
  1012. {
  1013.     help4("Somewhere in the math formula just ended, you used the",
  1014.     "stated character from an undefined font family. For example,",
  1015.     "plain TeX doesn't allow \\it or \\sl in subscripts. Proceed,",
  1016.     "and I'll try to forget that I needed that character.");
  1017. }
  1018.